www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char09/animated_bitmap_button/CAniButton.cpp
// AniButton.cpp : implementation file // #include "stdafx.h" #include "CDib.h" #include "CAniButton.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAniButton // Constant definition for the animation timer ID. const int ANIMATION_TIMER_ID = 512; // Default Constructor CAniButton::CAniButton() { m_pDIB = NULL; m_pDisabledDIB = NULL; m_uTimer = 0; m_nCurFrame = 0; m_nNumFrames = 0; m_nFramesPerSecond = 0; m_nFrameWidth = 0; m_nFrameHeight = 0; m_bStretchToFit = FALSE; m_hCursor = NULL; } // Destructor CAniButton::~CAniButton() { if(m_pDIB) delete m_pDIB; if(m_pDisabledDIB) delete m_pDisabledDIB; } BEGIN_MESSAGE_MAP(CAniButton, CButton) //{{AFX_MSG_MAP(CAniButton) ON_WM_SETCURSOR() ON_WM_DESTROY() ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAniButton message handlers // OnSetCursor method BOOL CAniButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (m_hCursor) { ::SetCursor(m_hCursor); return TRUE; } return CButton::OnSetCursor(pWnd, nHitTest, message); } // DrawItem method void CAniButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) { UINT uState = lpDIS->itemState; CRect rect; CDIB* pDIB = m_pDIB; int nYFrameOffset = 0; int nXFrameOffset = m_nCurFrame * m_nFrameWidth + 1; // // if the button is disabled and the timer // is enabled, disable the timer. // if((uState & ODS_DISABLED) && m_uTimer) { KillTimer(m_uTimer); m_uTimer = 0; m_nCurFrame = 0; } // // else if the button is not disabled, and the // timer is not enabled... Start the timer. // else if(!(uState & ODS_DISABLED) && !m_uTimer && m_nNumFrames > 1) { m_uTimer = SetTimer(ANIMATION_TIMER_ID, 1000 / m_nFramesPerSecond, NULL); } // // Determine the state and set the bitmap position accordingly. // if (uState & ODS_SELECTED) // The button is pressed { nYFrameOffset = m_nFrameHeight * 2; } else if (uState & ODS_FOCUS) // button has focus but not pressed { nYFrameOffset = m_nFrameHeight; } else if ((uState & ODS_DISABLED) && m_pDisabledDIB != NULL) { pDIB = m_pDisabledDIB; nXFrameOffset = 0; } // Get the device context for drawing. CDC* pDC = CDC::FromHandle(lpDIS->hDC); ASSERT(pDC); ASSERT(pDIB); if(pDC && pDIB) { // Draw the bitmap onto the window device context. rect.CopyRect(&lpDIS->rcItem); // // If we are not stretching (or shrinking) the bitmap // to fit inside of the window, just draw in the center. // if(!m_bStretchToFit) { pDIB->Draw( pDC, rect.left + (rect.Width() - m_nFrameWidth) / 2, rect.top + (rect.Height() - m_nFrameHeight) / 2, m_nFrameWidth, m_nFrameHeight, nXFrameOffset, nYFrameOffset ); } else // Strect the bitmap to fit! { pDIB->Stretch( pDC, rect.left, rect.top, rect.Width(), rect.Height(), nXFrameOffset, nYFrameOffset, m_nFrameWidth, m_nFrameHeight); } } } // The AutoLoad method is called to load the desired bitmaps before // the button is displayed. BOOL CAniButton::AutoLoad(UINT nID, CWnd* pParent, UINT nBitmapID, UINT nDisabledID, UINT nFramesPerSecond, UINT nNumFrames, BOOL bStretchToFit, BOOL bChangeFaceColor, UINT nCursorID) { // // First Create the bitmaps which the button will display. // Only the Main bitmap is needed because there is not // always a need to disable a button. // m_pDIB = new CDIB(nBitmapID); if( !m_pDIB || !m_pDIB->IsPaletteLoaded() ) { return FALSE; } if( nDisabledID != 0 ) { m_pDisabledDIB = new CDIB(nDisabledID); if( !m_pDisabledDIB->IsPaletteLoaded() ) { return FALSE; } } // Now make the call to Init to initialize the rest of the variables return Init(nID, pParent, nFramesPerSecond, nNumFrames, bStretchToFit, bChangeFaceColor, nCursorID); } // The AutoLoad method is called to load the desired bitmaps before // the button is displayed. BOOL CAniButton::AutoLoad(UINT nID, CWnd* pParent, const char* szFilename, const char* szDisabledFilename, UINT nFramesPerSecond, UINT nNumFrames, BOOL bStretchToFit, BOOL bChangeFaceColor, UINT nCursorID) { // // First Create the bitmaps which the button will display. // Only the Main bitmap is needed because there is not // always a need to disable a button. // m_pDIB = new CDIB(szFilename); if( !m_pDIB || !m_pDIB->IsPaletteLoaded() ) { return FALSE; } if( szDisabledFilename != NULL ) { m_pDisabledDIB = new CDIB(szDisabledFilename); if( !m_pDisabledDIB->IsPaletteLoaded() ) { return FALSE; } } // Now make the call to Init to initialize the rest of the variables return Init(nID, pParent, nFramesPerSecond, nNumFrames, bStretchToFit, bChangeFaceColor, nCursorID); } // Init method. Helper method for the AutoLoad methods. BOOL CAniButton::Init(UINT nID, CWnd* pParent, UINT nFramesPerSecond, UINT nNumFrames, BOOL bStretchToFit, BOOL bChangeFaceColor, UINT nCursorID) { // Attach the button to the dialog control if (!SubclassDlgItem(nID, pParent)) { return FALSE; } // // If we want to change the face color of the button // to match the windows System color... // if(bChangeFaceColor) { m_pDIB->ConvertColor( 0, 0, GetSysColor(COLOR_3DFACE) ); if(m_pDisabledDIB) { m_pDisabledDIB->ConvertColor( 0, 0, GetSysColor(COLOR_3DFACE) ); } } // // If the nNumFrames argument is 0, we can automatically calculate the // number of frames by dividing the width of the main bitmap by the // width of the Disabled Bitmap. NOTE: This can only be done if the // disabled bitmap is the same width as each individual frame in the // main bitmap. // if(nNumFrames == 0) { ASSERT(m_pDisabledDIB); m_nNumFrames = m_pDIB->GetWidth() / m_pDisabledDIB->GetWidth(); } else { m_nNumFrames = nNumFrames; } // set the other necessary member variables m_nFramesPerSecond = nFramesPerSecond; m_nFrameWidth = m_pDIB->GetWidth() / m_nNumFrames; m_nFrameHeight = m_pDIB->GetHeight() / 3; // Three Rows of animation. m_bStretchToFit = bStretchToFit; // Load the cursor to use for the button if desired. if(nCursorID != 0) { m_hCursor = AfxGetApp()->LoadCursor(nCursorID); } else { m_hCursor = NULL; } if(m_nNumFrames > 1) { m_uTimer = SetTimer(ANIMATION_TIMER_ID, 1000 / m_nFramesPerSecond, NULL); ASSERT(m_uTimer); } return TRUE; } // RealizePalette method. This method needs to be called whenever // the buttons parent window gets a WM_QUERYNEWPALETTE message. void CAniButton::RealizePalette() { // Determine which palette to realize. CPalette* pPal; IsWindowEnabled() ? pPal = m_pDIB->GetPalette() : pPal = m_pDisabledDIB->GetPalette(); // Get the buttons device context for drawing. CDC* pDC = GetDC(); // Realize the new palette. CPalette* pOldPalette = pDC->SelectPalette(pPal, FALSE); pDC->RealizePalette(); // Be nice to the existing palette. pDC->SelectPalette(pOldPalette, TRUE); pDC->RealizePalette(); ReleaseDC(pDC); // Redraw the button Invalidate(); } void CAniButton::OnTimer(UINT nIDEvent) { // Increment the frame wrapping if necessary m_nCurFrame = (m_nCurFrame >= m_nNumFrames-1) ? 0 : m_nCurFrame + 1; // invalidate the button, to force it to redraw Invalidate(FALSE); CButton::OnTimer(nIDEvent); } void CAniButton::OnDestroy() { // be sure that the timer is dead if(m_uTimer) { KillTimer(m_uTimer); } CButton::OnDestroy(); }